跳到主要内容

Spring整合Redis

整合 Redis

参考资料 官方文档 Spring Data 参考资料 官方文档 Spring Data Redis 参考资料 JedisConnectionFactory的设置连接方法过时(Deprecated)的解决方案

这个 spring-data-redis 是 Spring Data 的一个子项目,因为 Dao 层的代码大多都差不多,所以 Spring 就把这些 Dao 层的框架都制定一个通用的接口,用的时候只需遵循这个规定就好了

引入依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>

配置步骤如下

配置 Jedis 连接池配置

<!-- 这个是 redis.clients 包下的工具类 -->
<bean class="redis.clients.jedis.JedisPoolConfig" id="jedisPoolConfig">
<!--配置最大空闲连接数-->
<property name="maxIdle" value="10"/>
<!--配置最大连接数-->
<property name="maxTotal" value="50"/>
</bean>

配置 Jedis 连接工厂

JedisConnectionFactory 的设置连接方法过时

JedisConnectionFactory 从 Spring Data Redis 2.0 开始已经不推荐直接显示设置连接的信息了。

需要单独创建一个配置类,然后传进工厂类

一方面为了使配置信息与建立连接工厂解耦,另一方面抽象出 Standalone(单机)、Sentinel 和 RedisCluster(集群)三种模式的和一个统一的 Jedis 客户端连接配置类(用于配置连接池和SSL连接),使得我们可以更加灵活方便根据实际业务场景需要来配置连接信息。

<!--
配置连接工厂配置信息
JedisConnectionFacotory 从 Spring Data Redis 2.0开始已经不推荐直接显示设置连接的信息了
主要是为了支持其他的 Redis Client(例如 Lettuce)
所以抽象出 Standalone(单机)、Sentinel 和 RedisCluster(集群)三种模式的环境配置类
-->
<bean class="org.springframework.data.redis.connection.RedisStandaloneConfiguration" id="configuration">
<property name="hostName" value="127.0.0.1"/>
<property name="port" value="6379"/>
</bean>

注意:因为 Spring Data Redis 2.0开始分三种模式的环境,所以这个配置也有相应的变化,单机模式默认 无法传入连接池配置类 所以上面的那个连接池配置项只能给集群用,这里是单机模式不能添加配置(所以上面那个配了也用不了)

<!--
上面提到 Redis 支持多种客户端,这里则继续采用 Jedis
通过构造方法的形式把配置类传入连接工厂
这个构造方法为 public JedisConnectionFactory(RedisClusterConfiguration clusterConfig, JedisPoolConfig poolConfig)
可以直接传入连接池
-->
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" id="jedisConnectionFactory">
<constructor-arg ref="configuration"/>
</bean>

配置 Redis 模板对象

关键在于配置序列化器

<bean class="org.springframework.data.redis.core.RedisTemplate" id="redisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<!-- 还需要配置一个序列化器:能把储存的 key 和 value 做序列化处理的对象 -->
<!-- 配置默认的序列化器 -->
<!-- KeySerializer、valueSerializer 配置 Redis 中的 String 类型的 Key 与 Value 的序列化器 -->
<!-- HashKeySerializer、HashValueSerializer 配置 Redis 中的 Hash 类型的 Key 与 Value 的序列化器 -->

<!--例如这里的配置 String 类型的序列化器-->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<!--如果只存String类型的数据可以继续使用 StringRedisSerializer ,如果要存对象则使用 JdkSerializationRedisSerializer 序列化对象,然后存到 Redis 里面去-->
<!--<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>-->
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>

配置实体

对象要继承序列化的接口,否则无法序列化

@Data@ToString
public class User implements Serializable {
private int id;
private String name;
private String pwd;
}

单元测试

@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:applicationConfiguration.xml")
public class TestJedis {

@Autowired
public RedisTemplate<String, Object> redisTemplate;

@Test
public void test() {
// 这个 opsFor 后面跟类型(例如 Hash,这里的 Value 就是 String 类型)就是调用相应的方法

User user = new User();
user.setId(20);
user.setPwd("12345");
user.setName("alsritter");

// 可以实时修改序列化器
// redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
}

以 JSON 格式存储实体对象

前面使用 JDK 自带的序列化器对实体进行序列化存储实际上会使数据大 5 倍以上(大概),所以一般还是采用 JSON 来存储实体的数据

注意:使用了 JSON 作为序列化器,就无需让实体类继承 Serializable 接口了

首先需要引入依赖

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
@Test
public void test() {
// 这个 opsFor 后面跟类型(例如 Hash,这里的 Value 就是 String 类型)就是调用相应的方法
User user = new User();
user.setId(20);
user.setPwd("12345");
user.setName("alsritter");
// 使用 jackson 转换实体类(需要传入实体类的 User.class)
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(User.class));

redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}